package com.sdy.usercenter.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.auth.api.AuthApi;
import com.sdy.auth.api.model.UserInfo;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.StringUtil;
import com.sdy.mq.service.MqProducerService;
import com.sdy.mvc.controller.BaseController;
import com.sdy.mvc.utils.HttpUtil;
import com.sdy.usercenter.biz.constants.MqConstants;
import com.sdy.usercenter.biz.mapper.SysRoleResourceMapper;
import com.sdy.usercenter.biz.model.SysApplication;
import com.sdy.usercenter.biz.model.SysLog;
import com.sdy.usercenter.biz.model.SysRole;
import com.sdy.usercenter.biz.model.SysRoleResource;
import com.sdy.usercenter.biz.model.SysUser;
import com.sdy.usercenter.biz.model.vo.RoleAuthResPack;
import com.sdy.usercenter.biz.service.SysApplicationService;
import com.sdy.usercenter.biz.service.SysResourceService;
import com.sdy.usercenter.biz.service.SysRoleService;
import com.sdy.usercenter.biz.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 前端控制器
 * </p>
 *
 * @author zzq
 * @since 2019-06-14
 */
@Slf4j
@RestController
@RequestMapping("/sysRole")
public class SysRoleController extends BaseController {
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private MqProducerService mqProducerService;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private SysResourceService sysResourceService;
    @Autowired
    private SysApplicationService sysApplicationService;

    @GetMapping("/get")
    public Response get(Integer id) {
        SysRole role = sysRoleService.getById(id);
        return Response.success(role);
    }

    @GetMapping("/appTreeDataWithAuth")
    public Response appTreeDataWithAuth(String appCode, Integer roleId) throws BizException {
        return Response.success(sysResourceService.appTreeDataWithAuth(appCode, roleId));
    }

    /**
     * 应用列表
     */
    @GetMapping("/appListWithAuth")
    public Response appListWithAuth(Integer roleId) {
        List<SysApplication> appList = sysApplicationService.appListWithAuth(roleId);
        return Response.success(appList);
    }

    /**
     * 分页数据
     * @param request
     * @param page [current, size]
     * @return
     */
    @GetMapping("/pageData")
    public Response pageData(HttpServletRequest request, Page<SysRole> page, String name, Integer type, Integer state) {
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();

        wrapper.like(StringUtil.isNotBlank(name), SysRole::getName, name);
        wrapper.eq(type != null, SysRole::getType, type);
        wrapper.eq(state != null, SysRole::getState, state);
        wrapper.orderByDesc(SysRole::getId);

        IPage<SysRole> result = sysRoleService.page(page, wrapper);
        return Response.success(result);
    }

    /**
     * 分页数据
     */
    @GetMapping("/srcPageData")
    public Response srcPageData(HttpServletRequest request, Page<SysUser> page, Integer roleId) {
        Map<String, Object> queryMap = new HashMap<>();
        String name = request.getParameter("name");
        if (StringUtil.isNotBlank(name)) {
            queryMap.put("name", name);
        }
        IPage<SysUser> result = sysUserService.pageUserWithRole(page, queryMap, roleId, false);
        return Response.success(result);
    }

    /**
     * 分页数据
     */
    @GetMapping("/destPageData")
    public Response destPageData(HttpServletRequest request, Page<SysUser> page, Integer roleId) {
        Map<String, Object> queryMap = new HashMap<>();
        String name = request.getParameter("name");
        if (StringUtil.isNotBlank(name)) {
            queryMap.put("name", name);
        }
        IPage<SysUser> result = sysUserService.pageUserWithRole(page, queryMap, roleId, true);
        return Response.success(result);
    }

    /**
     * 添加用户
     */
    @PostMapping("/addUsers")
    public Response addUsers(HttpServletRequest request, @RequestBody List<Integer> userIdList, Integer roleId) throws Exception {
        if (userIdList != null && !userIdList.isEmpty()) {
            sysRoleService.addUsers(userIdList, roleId);
            // 日志消息
            UserInfo opUserInfo = ssoService.getUserInfo(request);
            SysRole role = sysRoleService.getById(roleId);
            mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                    SysLog.LogType.EDIT_ROLE_USER.getTypeS().concat(MqConstants.SEP_TOKEN)
                            .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                            .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                            .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                            .concat(opUserInfo.getUserName() + " 关联角色用户：" + role.getName() + " [" + role.getId() + "]" + " 用户ID："
                                    + userIdList.stream().map(String::valueOf).collect(Collectors.joining(",")))
            );
        }
        return Response.success();
    }

    /**
     * 移除用户
     */
    @PostMapping("/removeUsers")
    public Response removeUsers(HttpServletRequest request, @RequestBody List<Integer> userIdList, Integer roleId) throws Exception {
        if (userIdList != null && !userIdList.isEmpty()) {
            sysRoleService.removeUsers(userIdList, roleId);
            // 日志消息
            UserInfo opUserInfo = ssoService.getUserInfo(request);
            SysRole role = sysRoleService.getById(roleId);
            mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                    SysLog.LogType.EDIT_ROLE_USER.getTypeS().concat(MqConstants.SEP_TOKEN)
                            .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                            .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                            .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                            .concat(opUserInfo.getUserName() + " 移除角色用户：" + role.getName() + " [" + role.getId() + "]" + " 用户ID："
                                    + userIdList.stream().map(String::valueOf).collect(Collectors.joining(",")))
            );
        }
        return Response.success();
    }

    /**
     * 更新角色权限
     * @param
     * @return
     */
    @PostMapping("/updateAuth")
    public Response updateAuth(HttpServletRequest request, Integer roleId, @RequestBody List<RoleAuthResPack> roleAuthResPackList) throws Exception {
        Assert.isNull(roleId, "参数错误");
        SysRole item = sysRoleService.getById(roleId);
        Assert.isTrue(item != null && item.getReadonly().equals(1), "禁止修改该数据！");
        roleAuthResPackList = roleAuthResPackList == null ? new ArrayList<>() : roleAuthResPackList;
        sysRoleService.updateAuth(roleId, roleAuthResPackList);
        // 日志消息
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        SysRole role = sysRoleService.getById(roleId);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.EDIT_ROLE_AUTH.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 编辑角色权限：" + role.getName() + " [" + role.getId() + "]")
        );
        return Response.success();
    }

    /**
     * 保存数据
     * @param
     * @return
     */
    @PostMapping("/save")
    public Response save(HttpServletRequest request, @RequestBody SysRole sysRole) throws Exception {
        Assert.isBlank(sysRole.getName(), "角色名不能为空！");
        Assert.isBlank(sysRole.getCode(), "角色编码不能为空！");
        Integer exist = sysRoleService.lambdaQuery().eq(SysRole::getCode, sysRole.getCode()).count();
        Assert.isTrue(exist > 0, "角色编码重复，请修改！");
        sysRole.setState(1);
        sysRole.setReadonly(0);
        sysRole.setCreateTime(new Date());
        sysRoleService.save(sysRole);
        // 日志消息
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.ADD_ROLE.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 新增角色：" + sysRole.getName() + " [" + sysRole.getId() + "]")
        );
        return Response.success();
    }

    /**
     * 更新数据
     * @param
     * @return
     */
    @PostMapping("/update")
    public Response update(HttpServletRequest request, @RequestBody SysRole sysRole) throws Exception {
        Assert.isBlank(sysRole.getName(), "角色名不能为空！");
        Assert.isBlank(sysRole.getCode(), "角色编码不能为空！");
        Integer exist = sysRoleService.lambdaQuery().eq(SysRole::getCode, sysRole.getCode()).ne(SysRole::getId, sysRole.getId()).count();
        Assert.isTrue(exist > 0, "角色编码重复，请修改！");
        SysRole item = sysRoleService.getById(sysRole.getId());
        Assert.isTrue(item != null && item.getReadonly().equals(1), "禁止修改该数据！");
        sysRoleService.updateById(new SysRole()
                .setId(sysRole.getId())
                .setName(sysRole.getName())
                .setCode(sysRole.getCode())
                .setDescription(sysRole.getDescription()));
        // 日志消息
        UserInfo opUserInfo = ssoService.getUserInfo(request);
        mqProducerService.send(MqConstants.Tags.TAG_OP_LOG,
                SysLog.LogType.EDIT_ROLE.getTypeS().concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserId().toString()).concat(MqConstants.SEP_TOKEN)
                        .concat(DateUtil.formatTime(new Date())).concat(MqConstants.SEP_TOKEN)
                        .concat(HttpUtil.getIpAddr(request)).concat(MqConstants.SEP_TOKEN)
                        .concat(opUserInfo.getUserName() + " 编辑角色：" + sysRole.getName() + " [" + sysRole.getId() + "]")
        );
        return Response.success();
    }

    /**
     * 删除数据
     * @param id 主键
     * @return
     */
    @GetMapping("/delete")
    public Response delete(Integer id) throws BizException {
        SysRole item = sysRoleService.getById(id);
        Assert.isTrue(item != null && item.getReadonly().equals(1) || item.getAdmin().equals(1), "禁止删除该数据！");
        Assert.isTrue(sysRoleService.countUserByRole(id) > 0, "该角色下还有用户，请先解除用户的角色关系，再删除角色！");
        return Response.success(sysRoleService.removeById(id));
    }

    /**
     * 删除数据
     * @param id 主键
     * @return
     */
    @PostMapping("/deleteBatch")
    public Response deleteBatch(@RequestBody List<Integer> id) throws BizException {
        if (id != null && !id.isEmpty()) {
            Collection<SysRole> items = sysRoleService.listByIds(id);
            Assert.isTrue(items.stream().anyMatch(item -> item.getReadonly().equals(1) || item.getAdmin().equals(1)), "禁止修改该数据！");
            for (SysRole item : items) {
                Assert.isTrue(sysRoleService.countUserByRole(item.getId()) > 0, "角色 " + item.getName() + " 下还有用户，请先解除用户的角色关系，再删除角色！");
            }
            sysRoleService.removeByIds(id);
        }
        return Response.success();
    }

    /**
     * 禁用角色
     */
    @GetMapping("/disableRole")
    public Response disableRole(Integer id) {
        boolean r = sysRoleService.lambdaUpdate().eq(SysRole::getId, id).set(SysRole::getState, 2).update();
        if (!r) {
            return Response.error("禁用失败！");
        }
        return Response.success();
    }

    /**
     * 启用角色
     */
    @GetMapping("/enableRole")
    public Response enableRole(Integer id) {
        boolean r = sysRoleService.lambdaUpdate().eq(SysRole::getId, id).set(SysRole::getState, 1).update();
        if (!r) {
            return Response.error("启用失败！");
        }
        return Response.success();
    }
}
